package com.share.netdisk.user.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.constant.DefaultConstant;
import com.share.netdisk.user.dao.UserDao;
import com.share.netdisk.user.model.User;
import com.share.netdisk.user.model.UserContext;
import com.share.netdisk.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.share.constant.DefaultConstant.*;


@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public String login(User user) {
        //先将password加密
        String passwordAfter = passwordEncrypt(user.getPassword());

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, user.getUsername());
        User dbuser = userDao.selectOne(wrapper);
        //判断用户是否存在

        if (dbuser != null) {
            if (dbuser.getPassword().equals(passwordAfter)) {
                //登录成功.设置token,并设置有效期为1小时
                Date expiresAt = new Date(System.currentTimeMillis() + 1000 * 60 * 60);
                String token = JWT.create()
                        .setPayload(USERNAME_KEY, user.getUsername())
                        .setKey((JWT_KEY+System.currentTimeMillis()).getBytes(StandardCharsets.UTF_8))
                        .setExpiresAt(expiresAt)
                        .sign();
                //登录成功后将用户信息存入redis，设置有效期为1小时，用于后续的登录
//                redisTemplate.opsForValue().set(USER_TOKEN_KEY,token,System.currentTimeMillis()+ 1000 * 60 * 60, TimeUnit.MILLISECONDS);
                //将数据保存在ThreadLocal中,用于获取用户信息
                UserContext.setUser(dbuser);
                return token;
            }
            return PASSWORD_ERROR;
        }

        return USERNAME_NOT_EXIST;
    }

    //    注册
    @Override
    public String register(User user) {
        String passwordAfter = passwordEncrypt(user.getPassword());
        user.setPassword(passwordAfter);
        int insert = userDao.insert(user);
        if (insert > 0) {
            //注册成功,将用户对象信息存入redis，设置有效期为1小时，用于后续的登录
            redisTemplate.opsForValue().set(user.getUsername(), user, 1000 * 60 * 60, TimeUnit.MILLISECONDS);
            return REGISTER_SUCCESS;
        }
        return REGISTER_FAIL;
    }


    //用户是否存在
    @Override
    public boolean isExist(String username) {
        //先确定是否为空
        if (username == null || "".equals(username)) {
            return false;
        }
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, username);
        return userDao.selectOne(wrapper) != null;
    }


    //密码加密方法
    private String passwordEncrypt(String password) {
        return DigestUtil.sha256Hex(password + DefaultConstant.SALT);
    }

    // 生成验证码文本和图片
    @Override
    public ResponseEntity<byte[]> generateCaptcha() {
        // 定义字符集
        String charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        // 创建自定义的随机数生成器
        RandomGenerator randomGenerator = new RandomGenerator(charSet, 4);
        // 创建LineCaptcha对象
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        lineCaptcha.setGenerator(randomGenerator);
        // 重新生成验证码
        lineCaptcha.createCode();
        // 获取验证码文本
        String code = lineCaptcha.getCode();
        // 生成唯一标识符
        String uuid = UUID.randomUUID().toString();
        // 将验证码存入Redis，并设置有效期为1分钟
        redisTemplate.opsForValue().set(uuid, code, 1, TimeUnit.MINUTES);

        // 将验证码图片转换为字节数组
        byte[] imageBytes = lineCaptcha.getImageBytes();

        // 设置响应头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG);
        headers.set("X-Captcha-UUID", uuid);

        return new ResponseEntity<>(imageBytes, headers, 200);
    }

    // 校验验证码
    @Override
    public boolean validateCaptcha(String uuid, String userInput) {
        // 从Redis获取验证码
        String storedCode = (String) redisTemplate.opsForValue().get(uuid);
        if (storedCode == null) {
            // 如果Redis中没有找到该uuid对应的验证码，说明验证码已过期或不存在
            return false;
        }
        // 比较用户输入的验证码与Redis中的验证码是否一致
        return storedCode.equalsIgnoreCase(userInput);
    }

    //    注销
    @Override
    @Transactional
    public boolean logout(String username) {
        if (username != null) {
            try {
                // 删除 Redis 中的用户信息
                Boolean redisDelete = redisTemplate.delete(username);

                // 删除数据库中的用户信息
                int dbDelete = userDao.delete(new LambdaQueryWrapper<User>().eq(User::getUsername, username));

                // 判断删除操作是否成功
                if (redisDelete && dbDelete > 0) {
                    return true;
                } else {
                    // 如果其中一个操作失败，抛出异常以触发事务回滚
                    throw new RuntimeException("注销失败:不能删除Redis或者数据库的用户");
                }
            } catch (Exception e) {
                // 记录异常日志
                System.err.println("注销异常: " + e.getMessage());
                // 事务会自动回滚
                return false;
            }
        }
        return false;
    }


}
